#include "eint_key.h"

key_handler_t g_h1, g_h2, g_h3;

void eint_key_init(void)
{
	EXTI_InitTypeDef exti_value;
	NVIC_InitTypeDef nvic_value;
	
	/* 初始化GPIO */
	key_init(); 	
	

	/* 为什么使能AFIO时钟？
	 *
	 * STM32 的所有 GPIO 都引入到 EXTI 外部中断线上，
	 * 使得所有的 GPIO 都能作为外部中断的输入源，
	 * 所以如果把 GPIO 用作 EXTI 外部中断时，还需要开启 AFIO 时钟。
	 * or
	 * 在STM32F10x中文参考手册8.2.5 外部中断/事件线路映像中
	 * 使用到了AFIO_EXTICRx 寄存器进行读写操作，所以使能AFIO时钟。
	 */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	/* 配置EXTI GPIO中断线 */
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource8);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource9);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
	
	/* 初始化EXTI */
	exti_value.EXTI_Line = EXTI_Line9 | EXTI_Line8; 		// PC9对应EXTI9 PC8对应EXTI8
	exti_value.EXTI_Mode = EXTI_Mode_Interrupt; 			// 中断模式
	exti_value.EXTI_Trigger = EXTI_Trigger_Falling; 		// 下降沿触发
	exti_value.EXTI_LineCmd = ENABLE; 						// 使能
	EXTI_Init(&exti_value);
	
	exti_value.EXTI_Line = EXTI_Line0; 
	exti_value.EXTI_Mode = EXTI_Mode_Interrupt; 			// 中断模式
	exti_value.EXTI_Trigger = EXTI_Trigger_Rising; 			// 上升沿触发
	exti_value.EXTI_LineCmd = ENABLE; 						// 使能
	EXTI_Init(&exti_value);

	/* 初始化NVIC */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);			// 组优先 2bit 子优先 2bit
	
	nvic_value.NVIC_IRQChannel = EXTI9_5_IRQn; 				// 中断号
	nvic_value.NVIC_IRQChannelCmd = ENABLE;
	nvic_value.NVIC_IRQChannelPreemptionPriority = 2;
	nvic_value.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&nvic_value);
	
	nvic_value.NVIC_IRQChannel = EXTI0_IRQn; 				// 中断号
	NVIC_Init(&nvic_value);
}

/* 通过中断向量表得知EXTI Line 9..5的中断函数 */
void EXTI9_5_IRQHandler(void)
{
	// PC9 PC8
	if (EXTI_GetITStatus(EXTI_Line9)) { // 区分那条线触发了中断
		g_h1();
		EXTI_ClearITPendingBit(EXTI_Line9); // 清除中断位!!!!!!!!!! 
	} else if (EXTI_GetITStatus(EXTI_Line8)){
		g_h2();
		EXTI_ClearITPendingBit(EXTI_Line8);
	}
}

void EXTI0_IRQHandler(void)
{
	g_h3();
	EXTI_ClearITPendingBit(EXTI_Line0);
}

void set_key_handlers(key_handler_t h1, key_handler_t h2, key_handler_t h3)
{
	g_h1 = h1;
	g_h2 = h2;
	g_h3 = h3;
}
